""" Utility class to read Datastore backup file.
"""

from google.appengine.api import datastore
from google.appengine.api.files import file, records
from google.appengine.datastore import entity_pb

class DatastoreBackupReader(object):
  """DatastoreBackupReader is a utility class to read backup file stored either
     on cloud storage or downloaded to local file system via gsutil.
  """
  _BUFFER_SIZE = 512*1024

  def readFromLocal(self, filename, entityrenderer):
    """Reads a local backup file.

    Args:
      filename: qualified name for backup file in local file system.
      entityrenderer: An implementation of EntityRenderer class.
    """
    f = open(filename, 'r')
    recordsReader = records.RecordsReader(f)
    for record in recordsReader:
      entityrenderer.render(record)
    f.close()

  def readFromCloudStore(self, filename, entityrenderer):
    """Reads a file from cloud store.

    Args:
      filename: qualified name for backup file in cloud storage. It should be a
                readable file in format /gs/<bucket>/<key>
      entityrenderer: An implementation of EntityRenderer class.
    """
    f = file.open(filename, buffering = self._BUFFER_SIZE)
    recordsReader = records.RecordsReader(f)
    for record in recordsReader:
      entityrenderer.render(record)
    f.close()


class EntityRenderer(object):
  """EntityRenderer is a callback DatastoreBackupReader. This class should be
     subclassed to write rules for converting entity dictionary to user defined
     objects.
  """

  def render(self, record):
    """Callback method - should be called once per record retrieved from backup
       file.

    Args:
      record: bytes for a record.
    """
    pb = entity_pb.EntityProto(record)
    entity = datastore.Entity.FromPb(pb)
    self.process_entity(entity)

  def process_entity(self, entity):
    """This method should be overridden to handle entity as needed.
    e.g.- a.) entity.kind() - gives entity's kind.
          b.) entity.namespace()- gives namespace of this entity.
          c.) entity.get(property) - gives value for a property.
    Args:
      entity: object of type google.appengine.api.datastore.Entity
    """
    raise NotImplementedError()
